﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.Xml.Serialization;

namespace MazeWars
{
    public class Player
    {
        protected Vector2 cursorPosition, temp;
        protected List<Trunk> trunk;
        protected bool foundMove, spellCharging, castingSpell;
        protected int branchNum, spellID;
        protected int button;
        protected int[] loc;
        protected int health, maxHealth;
        protected int prevLoc, prevPrevLoc;
        const int MAX_BRANCHES = 13;

        public Vector2 Cursor
        {
            set
            {
                cursorPosition = value;
            }
            get
            {
                return cursorPosition;
            }
        }

        public Trunk MyTrunk
        {
            set
            {
                trunk.Add(value);
            }
            get
            {
                return trunk[branchNum];
            }
        }

        public List<Trunk> TrunkList
        {
            set
            {
                trunk = value;
            }
            get
            {
                return trunk;
            }
        }

        public int Health
        {
            set
            {
                health = value;
            }
            get
            {
                return health;
            }
        }

        public int MaxHealth
        {
            set
            {
                maxHealth = value;
            }
            get
            {
                return maxHealth;
            }
        }

        public Player()
        {
            temp = Vector2.Zero;
            cursorPosition = Vector2.Zero;
            trunk = new List<Trunk>();
            branchNum = 0;
            prevLoc = 0;
            prevPrevLoc = 0;
            spellCharging = false;
            castingSpell = false;
            spellID = -1;
            health = 100;
            maxHealth = 100;
            loc = new int[MAX_BRANCHES];
            for (int i = 0; i < MAX_BRANCHES; i++)
            {
                loc[i] = 0;
            }
        }

        public virtual void reset()
        {
            health = maxHealth;
            spellID = -1;
            spellCharging = false;
            castingSpell = false;
            for (int i = 0; i < MAX_BRANCHES; i++)
            {
                loc[i] = 0;
            }
            branchNum = 0;

            if (trunk != null)
            {
                trunk.Clear();
            }
        }

        public Vector2 canAdvance(Keys key)
        {
            foundMove = false;
            switch (key)
            {
                case Keys.A: button = 4; break;
                case Keys.S: button = 5; break;
                case Keys.D: button = 6; break;
                case Keys.W: button = 7; break;
                case Keys.Up: button = 2; break;
                case Keys.Down: button = 3; break;
                case Keys.Left: button = 0; break;
                case Keys.Right: button = 1; break;
            }
            temp.X = MyTrunk.TrunkTiles[loc[branchNum]].X;
            temp.Y = MyTrunk.TrunkTiles[loc[branchNum]].Y;
            if (loc[branchNum] + 1 < MyTrunk.TrunkTiles.Count)
            {
                if (MyTrunk.TrunkTiles[loc[branchNum] + 1].Button == button)
                {
                    prevPrevLoc = prevLoc;
                    prevLoc = loc[branchNum];
                    loc[branchNum]++;
                    foundMove = true;
                    if (MyTrunk.TrunkTiles[prevLoc].Type % 2 == 1 && MyTrunk.TrunkTiles[prevLoc].Type > 1 && MyTrunk.TrunkTiles[prevPrevLoc] == MyTrunk.TrunkTiles[loc[branchNum]])
                    {
                        chargeSpell(MyTrunk.SpellID);
                    }
                }
            }
            if (loc[branchNum] - 1 >= 0 && !foundMove)
            {
                if (MyTrunk.TrunkTiles[loc[branchNum] - 1].Button == button)
                {
                    prevPrevLoc = prevLoc;
                    prevLoc = loc[branchNum];
                    loc[branchNum]--;
                    foundMove = true;
                    if (MyTrunk.TrunkTiles[prevLoc].Type % 2 == 1 && MyTrunk.TrunkTiles[prevLoc].Type > 1 && MyTrunk.TrunkTiles[prevPrevLoc] == MyTrunk.TrunkTiles[loc[branchNum]])
                    {
                        chargeSpell(MyTrunk.SpellID);
                    }
                }
            }
            if (MyTrunk.TrunkTiles[loc[branchNum]].Type % 2 == 1 && !foundMove)
            {
                int attachedBranch = MyTrunk.TrunkTiles[loc[branchNum]].AttachedBranch;
                if (attachedBranch != 0 && trunk[attachedBranch].TrunkTiles[loc[attachedBranch]].Button == button && !trunk[attachedBranch].OnCooldown)
                {
                    branchNum = attachedBranch;
                    foundMove = true;
                }
            }
            if (branchNum > 0 && loc[branchNum] == 0 && !foundMove)
            {
                Trunk nextTrunk = prevTrunk(branchNum);
                for (int i = 0; i < nextTrunk.TrunkTiles.Count; i++)
                {
                    if (nextTrunk.TrunkTiles[i].AttachedBranch == branchNum && nextTrunk.TrunkTiles[i].Button == button)
                    {
                        if (spellCharging && nextTrunk.Equals(trunk[0]))
                        {
                            activateCooldown(branchNum);
                            spellCharging = false;
                            castingSpell = true;
                        }
                        branchNum = trunkNumber(nextTrunk);
                    }
                }
            }
            return MyTrunk.TrunkTiles[loc[branchNum]].Pos - temp;
        }

        public int getNode(int nodeNum, Trunk t)
        {
            for (int i = 0; i < t.TrunkTiles.Count; i++)
            {
                if (t.TrunkTiles[i].AttachedBranch == nodeNum)
                {
                    return i;
                }
            }
            return -1;
        }

        public void populateTree(List<Trunk> t)
        {
            int node;
            int branch;
            trunk = t;
            Vector2 temp = Vector2.Zero;

            foreach (Trunk trunkItr in trunk)
            {
                for (int i = 1; i < trunk.Count; i++)
                {
                    if ((node = getNode(i, trunkItr)) != -1)
                    {
                        branch = trunkItr.TrunkTiles[node].AttachedBranch;
                        for (int j = 0; j < trunk[branch].TrunkTiles.Count; j++)
                        {
                            temp.X = trunk[branch].Offset.X;
                            temp.Y = trunk[branch].Offset.Y;
                            trunk[branch].TrunkTiles[j].Pos += temp;
                        }
                    }
                }
            }
        }

        protected void chargeSpell(int id)
        {
            spellCharging = true;
            spellID = id;
        }

        public void manageCooldown(GameTime gt)
        {
            foreach (Trunk t in trunk)
            {
                if (t.OnCooldown)
                {
                    t.manageCooldown(gt);
                }
            }
        }

        public virtual int castSpell()
        {
            if (castingSpell)
            {
                castingSpell = false;
                return spellID;
            }
            return -1;
        }

        public void dealDamage(int dmg)
        {
            health -= dmg;
        }

        public Trunk prevTrunk(int index)
        {
            foreach (Trunk trunkItr in trunk)
            {
                foreach (Tile t in trunkItr.TrunkTiles)
                {
                    if (t.AttachedBranch == index)
                    {
                        return trunkItr;
                    }
                }
            }
            return null;
        }

        public int trunkNumber(Trunk t)
        {
            for (int i = 0; i < trunk.Count; i++)
            {
                if (trunk[i] == t)
                {
                    return i;
                }
            }

            return -1;
        }

        public void activateCooldown(int index)
        {
            int number = index;
            while (trunk[number].TrunkTiles[trunk[number].TrunkTiles.Count - 1].AttachedBranch != 0)
            {
                trunk[number].OnCooldown = true;
                number = trunk[number].TrunkTiles[trunk[number].TrunkTiles.Count - 1].AttachedBranch;
            }
            trunk[number].OnCooldown = true;
        }

        //Virtual method to access update in the AI class
        public virtual Keys update(GameTime gt)
        { return Keys.None; }

        public virtual void SetSpells(List<Spell> s)
        { }
    }//End of class Player
}
